package ru.spb.osll.myfit.client.manager;

import java.util.TreeMap;

import ru.spb.osll.myfit.client.dialog.DialogEventListener;
import ru.spb.osll.myfit.client.dialog.IncludePageDialog;
import ru.spb.osll.myfit.client.dialog.TableCreatorDialog;
import ru.spb.osll.myfit.client.dialog.TextInputDialog;
import ru.spb.osll.myfit.client.event.PageEvent;
import ru.spb.osll.myfit.client.log.RemoteLogger;
import ru.spb.osll.myfit.client.service.CreateHelperService;
import ru.spb.osll.myfit.client.service.CreateHelperServiceAsync;
import ru.spb.osll.myfit.client.widget.PageEventListener;
import ru.spb.osll.myfit.client.widget.PageWidget;
import ru.spb.osll.myfit.common.PageElement;
import ru.spb.osll.myfit.common.Table;
import ru.spb.osll.myfit.common.WikiText;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.DialogBox;
import ru.spb.osll.myfit.client.dialog.AddContentDialog;

public class PageElementManager implements PageEventListener {

  private final CreateHelperServiceAsync m_createHelperService = GWT.create(CreateHelperService.class);

  private TableCreatorDialog m_TableCreatorDialog;

  private IncludePageDialog m_IncludePageDialog;

  private TextInputDialog m_textInputDialog;

  private DialogEventListener m_dialogEventListener;

  private DialogBox m_errorDialog;

  private AddContentDialog m_contentDialog;

  public PageElementManager() {
    m_dialogEventListener = createDialogListener();
    m_TableCreatorDialog = new TableCreatorDialog(m_dialogEventListener);
    loadTemplates();
    m_IncludePageDialog = new IncludePageDialog(m_dialogEventListener);
    m_textInputDialog = new TextInputDialog(m_dialogEventListener);
    m_contentDialog = new AddContentDialog(m_dialogEventListener);
  }

  private DialogEventListener createDialogListener() {
    DialogEventListener listener = new DialogEventListener() {

      @Override
      public void createElement(String input, PageEvent sourceEvent) {
        switch (sourceEvent.getType()) {
        case ADD_INCLUDE:
          addInclude(input, sourceEvent);
          break;
        case ADD_TABLE:
          addTable(input, sourceEvent);
          break;
        case ADD_WIKI:
          addWikiText(input, sourceEvent);
          break;
        case ADD_CONTENT:
          int level = parseLevel(input);
          addContent(level, sourceEvent);
          break;
        default:
          break;
        }
      }
    };
    return listener;
  }

  private void showTextInputDialog(PageEvent sourceEvent) {
    m_textInputDialog.setSourceEvent(sourceEvent);
    m_textInputDialog.center();
    m_textInputDialog.show();
  }

  private void showTableCreator(PageEvent sourceEvent) {
    m_TableCreatorDialog.setSourceEvent(sourceEvent);
    m_TableCreatorDialog.center();
    m_TableCreatorDialog.show();
  }

  private void showIncludeDialog(PageEvent sourceEvent) {
    m_IncludePageDialog.setSourceEvent(sourceEvent);
    m_IncludePageDialog.center();
    m_IncludePageDialog.show();
  }

  private void showContentDialog(PageEvent sourceEvent){
    m_contentDialog.setSourceEvent(sourceEvent);
    m_contentDialog.center();
    m_contentDialog.show();
  }

  private void insertPageElement(PageElement pageElement, PageEvent event) {
    PageWidget parent = event.getParent();
    parent.insertPageElemnt(event.getSource(), pageElement, event.isBefore());
  }

  @Override
  public void actionPerformed(PageEvent event) {

    switch (event.getType()) {
    case ADD_INCLUDE:
      showIncludeDialog(event);
      break;
    case ADD_TABLE:
      showTableCreator(event);
      break;
    case ADD_WIKI:
      showTextInputDialog(event);
      break;
    case ADD_CONTENT:
      showContentDialog(event);
    default:
      break;
    }
  }

  public void addInclude(final String includePath, final PageEvent sourceEvent) {
    m_createHelperService.loadInclude(sourceEvent.getParent().getPagePath(), includePath,
        new AsyncCallback<PageElement>() {

          public void onFailure(final Throwable caught) {
            m_errorDialog.center();
          }

          public void onSuccess(final PageElement result) {
            insertPageElement(result, sourceEvent);
          }
        });
  }

  private int parseLevel(String content){
      int pos = content.indexOf("-R");
      if(pos<0 || pos==content.length()-2)
          return 0;
      return Integer.parseInt(content.substring(pos+2));
  }

  public void addWikiText(final String wikiText, final PageEvent sourceEvent) {

    m_createHelperService.convertWikiToHtml(wikiText, new AsyncCallback<String>() {

      @Override
      public void onFailure(Throwable arg0) {
        m_errorDialog.center();
      }

      @Override
      public void onSuccess(String html) {
        insertPageElement(new WikiText(wikiText, html), sourceEvent);
      }

    });
  }

  public void addTable(String tableName, final PageEvent sourceEvent) {
    m_createHelperService.getTemplate(tableName, new AsyncCallback<Table>() {
      public void onFailure(final Throwable caught) {
        m_errorDialog.center();
      }

      public void onSuccess(final Table table) {
        insertPageElement(table, sourceEvent);
      }
    });
  }

  private void loadTemplates() {
    m_createHelperService.loadTemplates(new AsyncCallback<TreeMap<String, String>>() {
      public void onFailure(Throwable caught) {
        RemoteLogger.error("Error submitting fixture list");
      }

      public void onSuccess(TreeMap<String, String> tables) {
        m_TableCreatorDialog.setFixturesName(tables);
      }
    });
  }

  public void addErrorDialog(DialogBox mErrorDialog) {
    m_errorDialog = mErrorDialog;

  }

  public void addContent(int level,final PageEvent event ){
    m_createHelperService.createContent(level, event.getParent().getPagePath(), new  AsyncCallback<PageElement>() {

      @Override
      public void onFailure(Throwable arg0) {
        m_errorDialog.center();
      }

      @Override
      public void onSuccess(PageElement arg0) {
        insertPageElement(arg0, event); 
      }
    });
  }
}
